﻿using System;
using System.IO;
using System.Text;

namespace CrmLinkBuddyWpf
{
    /// <summary>
    /// Provides functionality to create an HTML file with hyperlinks to Dynamics CRM entity records. 
    /// </summary>
    internal class CrmLinkHtmlBuilder
    {
        private string _htmlFilePath = null;
        private StringBuilder _htmlContent;
        private string _crmBaseUrl;

        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="crmOrgUrl">The full URL for a CRM organization's service endpoint (/XRMServices/2011/Organization.svc).</param>
        public CrmLinkHtmlBuilder(string crmOrgUrl)
        {
            Initialize(crmOrgUrl);
        }

        /// <summary>
        /// The path to the HTML file that contains the CRM hyperlinks and other provided text.
        /// </summary>
        public string HtmlFilePath
        {
            get { return _htmlFilePath; }
        }

        #region Public methods

        /// <summary>
        /// Write plain (non-link related) text to the HTML file.
        /// </summary>
        /// <param name="text">Text string to write to the HTML file.</param>
        public void OutputPlainTextLine(string text)
        {
            AddTextToHtmlContent(text);
        }

        /// <summary>
        /// Use this method to write a CRM form hyperlink to the HTML file. This is the method to call when a record is found in CRM for a GUID.
        /// </summary>
        /// <param name="originalTextLine">The original text line from the user-provided text.</param>
        /// <param name="entityName">The entity logical name for the found/matched GUID.</param>
        /// <param name="recordGuid">The CRM record GUID (as a string).</param>
        /// <param name="entityRecordName">The primary name (text) for the entity record.</param>
        public void OutputLinkTextLine(string originalTextLine, string entityName, string recordGuid, string entityRecordName)
        {
            // Example CRM form hyperlink: http://myorg.crm.dynamics.com/main.aspx?etn=account&pagetype=entityrecord&id=%7B91330924-802A-4B0D-A900-34FD9D790829%7D
            string newTextLine = originalTextLine;
            string recordUrl = _crmBaseUrl + string.Format("main.aspx?etn={0}&pagetype=entityrecord&id=%7B{1}%7D", entityName, recordGuid);
            newTextLine = newTextLine.Replace(recordGuid, string.Format("<A HREF='{0}' TARGET='_blank'>[{1}][{2}]</A>", recordUrl, entityName, entityRecordName));
            AddTextToHtmlContent(newTextLine);
        }

        /// <summary>
        /// Create HTML from plain text. This prepares plain text for displaying in a web browser.
        /// </summary>
        /// <param name="text">Input text</param>
        /// <returns>Returns the original text with HTML tags for line breaks, special characters, etc.</returns>
        public static string ConvertTextToHtml(string text)
        {
            StringBuilder sb = new StringBuilder(text);

            // Replace all double white spaces with a single white space and &nbsp;
            sb.Replace("  ", " &nbsp;");

            //Convert the brackets into HTML equivalents
            sb.Replace("<", "&lt;");
            sb.Replace(">", "&gt;");

            // Convert the double quote
            sb.Replace("\"", "&quot;");

            // Create a StringReader from the processed string of the StringBuilder
            StringReader sr = new StringReader(sb.ToString());
            StringWriter sw = new StringWriter();

            // Loop while next character exists
            while (sr.Peek() > -1)
            {
                // Read a line from the string and store it to a temp variable
                string temp = sr.ReadLine();

                // Write the string with the HTML break tag
                // Note here write method writes to a Internal StringBuilder object created automatically
                sw.Write(temp + "<br>" + Environment.NewLine);
            }

            //Return the final processed text
            return sw.GetStringBuilder().ToString();
        }

        /// <summary>
        /// Write the HTML content being formulated in this class instance to an HTML file on disk.
        /// </summary>
        public void WriteToHtmlFile()
        {
            AddTextToHtmlContent(GetHtmlEndingContent());
            using (FileStream fileStream = new FileStream(_htmlFilePath,
                FileMode.CreateNew,
                FileAccess.Write,
                FileShare.None))
            {
                using (StreamWriter streamWriter = new StreamWriter(fileStream))
                {
                    streamWriter.Write(_htmlContent);
                }
            }
        }

        #endregion

        #region Private methods

        /// <summary>
        /// Initialize the class with default values.
        /// </summary>
        /// <param name="crmOrgFullApiPath"></param>
        private void Initialize(string crmOrgFullApiPath)
        {
            _htmlFilePath = Path.GetTempFileName() + ".html";
            _htmlContent = new StringBuilder();
            AddTextToHtmlContent(GetHtmlBeginningContent());
            _crmBaseUrl = crmOrgFullApiPath.Replace("XRMServices/2011/Organization.svc", "").Replace(".api.", ".");
        }

        /// <summary>
        /// Adds a text line to the HTML content being constructed.
        /// </summary>
        private void AddTextToHtmlContent(string text)
        {
            _htmlContent.AppendLine(text);
        }

        /// <summary>
        /// Get the starting HTML tags for the full HTML content being constructed.
        /// </summary>
        private string GetHtmlBeginningContent()
        {
            return "<html><head></head><body style='font-family:Courier New,Courier,Monospace; font-size:small'>\n";
        }

        /// <summary>
        /// Get the ending HTML tags for the full HTML content being constructed.
        /// </summary>
        private string GetHtmlEndingContent()
        {
            return "</body></html>";
        }

        #endregion

    }
}
